#import "ALDeviceInfoTools.h"
#import "ALUtils.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#import <CoreLocation/CoreLocation.h>
#import <CoreLocation/CLLocationManagerDelegate.h>
#import <AdSupport/ASIdentifierManager.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
#import "UIDevice+Hardware.h"

#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])

const char* lu_jailbreak_tool_pathes[] = {
    "/Applications/Cydia.app",
    "/Library/MobileSubstrate/MobileSubstrate.dylib",
    "/bin/bash",
    "/usr/sbin/sshd",
    "/etc/apt"
};


@implementation ALDeviceInfoTools


//常用的设备信息
+(NSDictionary*)deviceInfo{
    NSString* ppi = [NSString stringWithFormat:@"%.2f",APP_SCALE];
    NSString* heightInPixel = [NSString stringWithFormat:@"%.0f",APP_HEIGHT_IN_PIXEL];
    NSString* widthInPixels = [NSString stringWithFormat:@"%.0f",APP_WIDTH_IN_PIXEL];
    NSString* height = [NSString stringWithFormat:@"%.0f",APP_HEIGHT];
    NSString* width = [NSString stringWithFormat:@"%.0f",APP_WIDTH];
    NSString* osVersion = [NSString stringWithFormat:@"%.1f",CURRENT_OS_VERSION];
    
    NSMutableDictionary* info = [[NSMutableDictionary alloc]initWithObjectsAndKeys:[ALDeviceInfoTools deviceDesc],@"desc",@"iOS",@"os",osVersion,@"osVersion",width,@"width",height,@"height",widthInPixels,@"widthInPixels",heightInPixel,@"heightInPixels",ppi,@"ppi", nil];

    NSString *deviceName = [ALDeviceInfoTools deviceName];
    NSString *deviceBrand = [ALDeviceInfoTools deviceBrand];
    NSString *OSVersion = [ALDeviceInfoTools OSVersion];
    NSString *deviceToken = [ALDeviceInfoTools deviceToken];
    NSString *IDFA = [ALDeviceInfoTools IDFA];
    NSString *IDFV = [ALDeviceInfoTools IDFV];
    NSDictionary *deviceInfo = @{
        @"b":deviceName?:@"",
        @"c":deviceBrand?:@"",
        @"d":OSVersion?:@"",
        @"f":deviceToken?:@"",
        @"g":IDFA?:@"",
        @"h":IDFV?:@""
    };
    [info addEntriesFromDictionary:deviceInfo];
    return info;
}


+ (NSString *)deviceDesc {
    UIDevice *device = [[UIDevice alloc] init];
    return [device hardwareSimpleDescription];
}


#pragma 设备相关信息
+(CGSize)deviceSizeInPixels{
    if(CURRENT_OS_VERSION>=8.000000f){
        return [UIScreen mainScreen].nativeBounds.size;
    }
    return CGSizeMake(APP_WIDTH*2,APP_HEIGHT*2);
}


// 颜色反转功能
+ (NSString *)invertedColorsEnabled{
    BOOL isEnable = UIAccessibilityIsInvertColorsEnabled();
    return isEnable?@"1":@"0";
}

// Language
+ (NSString *)language{
    @try {
        NSArray *languageArray = [NSLocale preferredLanguages];
        NSString *language = [languageArray objectAtIndex:0];
        if (language == nil || language.length <= 0) {
            return @"";
        }
        return language;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// Mono Audio enabled
+ (NSString *)monoAudioEnabled{
    BOOL isEnable = UIAccessibilityIsMonoAudioEnabled();
    return isEnable?@"1":@"0";
}

//VoiceOver enabled
+ (NSString *)voiceOverEnabled{
    BOOL isEnable = UIAccessibilityIsVoiceOverRunning();
    return isEnable?@"1":@"0";
}

// VoiP Allowed
+ (NSString *)voipAllowed{
    @try {
        static CTTelephonyNetworkInfo *__voip_telephonyInfo = nil;
        static dispatch_once_t dispatchToken;
        if (!__voip_telephonyInfo) {
            dispatch_once(&dispatchToken, ^{
                __voip_telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
            });
        }
        CTCarrier *carrier = [__voip_telephonyInfo subscriberCellularProvider];
        BOOL carrierVOIP = [carrier allowsVOIP];
        return carrierVOIP?@"1":@"0";;
    }
    @catch (NSException *exception) {
        return @"0";
    }
}

// 是否越狱
+ (BOOL)jailbroken {
    static BOOL isAccessFiles = NO;
    static BOOL isJailBreak = NO;
    if (isAccessFiles) {
        return isJailBreak;
    }
    isAccessFiles = YES;
    
    for (int i=0; i<ARRAY_SIZE(lu_jailbreak_tool_pathes); i++) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:lu_jailbreak_tool_pathes[i]]]) {
            isJailBreak = YES;
        }
    }
    return isJailBreak;
}

// Country
+ (NSString *)country{
    @try {
        NSLocale *locale = [NSLocale currentLocale];
        NSString *country = [locale localeIdentifier];
        if (country == nil || country.length <= 0) {
            return @"";
        }
        return country;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// Country Code
+ (NSString *)countryCode{
    @try {
        NSString *countryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
        return countryCode;
    }
    @catch (NSException *exception) {
        // Error finding the name
        return nil;
    }
}

// Device Model
+ (NSString *)deviceModel{
    @try {
        if ([[UIDevice currentDevice] respondsToSelector:@selector(model)]) {
            NSString *deviceModel = [[UIDevice currentDevice] model];
            return deviceModel;
        } else {
            return @"";
        }
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// Device Name
+ (NSString *)deviceName{
    @try {
        if ([[UIDevice currentDevice] respondsToSelector:@selector(name)]) {
            NSString *deviceName = [[UIDevice currentDevice] name];
            return deviceName;
        } else {
            return @"";
        }
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// Device Brand
+ (NSString *)deviceBrand{
    @try {
        size_t size = 100;
        char *hw_machine = malloc(size);
        int name[] = {CTL_HW,HW_MACHINE};
        sysctl(name, 2, hw_machine, &size, NULL, 0);
        NSString *hardware = [NSString stringWithUTF8String:hw_machine];
        free(hw_machine);
        return hardware;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// OS Version
+ (NSString *)OSVersion{
    @try {
        if ([[UIDevice currentDevice] respondsToSelector:@selector(systemVersion)]) {
            NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
            return systemVersion;
        } else {
            return @"";
        }
    }
    @catch (NSException *exception) {
        return @"";
    }
}

// OS Name
+ (NSString *)OSName{
    @try {
        if ([[UIDevice currentDevice] respondsToSelector:@selector(systemName)]) {
            NSString *systemName = [[UIDevice currentDevice] systemName];
            return systemName;
        } else {
            return @"";
        }
    }
    @catch (NSException *exception) {
        return @"";
    }
}

+ (NSString *)screenSize{
    UIScreen *screen = [UIScreen mainScreen];
    CGFloat width = screen.bounds.size.width;
    CGFloat height = screen.bounds.size.height;
    
    return [NSString stringWithFormat:@"%.0f*%.0f",width, height];
}

// 屏幕分辨率
+ (NSString *)screenPix{
    UIScreen *screen = [UIScreen mainScreen];
    CGFloat width = screen.bounds.size.width;
    CGFloat height = screen.bounds.size.height;
    
    CGFloat scale_screen = [UIScreen mainScreen].scale;
    
    return [NSString stringWithFormat:@"%.0f*%.0f",width*scale_screen, height*scale_screen];
}

+ (NSString *)userAgent{
    NSString *userAgent = nil;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
#if TARGET_OS_IOS
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
#elif TARGET_OS_WATCH
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
    userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif
#pragma clang diagnostic pop
    if (userAgent) {
        if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
            NSMutableString *mutableUserAgent = [userAgent mutableCopy];
            if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
                userAgent = mutableUserAgent;
            }
        }
    }
    return userAgent;
}

// Mobile accept
+ (NSString *)mobileAccept{
    return @"gzip, deflate";
}

+ (NSString *)systemFontList{
    @try {
        NSArray *familyNames = [UIFont familyNames];
        NSMutableString *result = [[NSMutableString alloc] init];
        for (NSString *family in familyNames) {
            [result appendString:family];
        }
        return result;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

+ (NSString *)deviceToken{
    NSString *deviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"token"];
    return deviceToken;
}

// Advertising Identifier 广告标识符 和设备绑定
+ (NSString *)IDFA{
    NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    return idfa;
}

// Identities For Vendor 和APP绑定
+ (NSString *)IDFV{
    NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];
    return identifierForVendor;
}

// carrierName
+ (NSString *)carrierName {    
    @try {
        // 修复获取运营商的一个bug
        // http://stackoverflow.com/questions/33748737/coretelephony-crash-non-reproducible
        static CTTelephonyNetworkInfo *__carrier_telephonyInfo = nil;
        static dispatch_once_t dispatchToken;
        if (!__carrier_telephonyInfo) {
            dispatch_once(&dispatchToken, ^{
                __carrier_telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
            });
        }
        CTCarrier *carrier = [__carrier_telephonyInfo subscriberCellularProvider];
        NSString *carrierName = [carrier carrierName];
        if (carrierName == nil || carrierName.length <= 0) {
            return @"";
        }
        return carrierName;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

+ (NSString *)internetConnectionType{
    return [ALHttpUtils newtworkType];
}

+ (NSString *)currentPublicIP{
    return [ALHttpUtils getIPAddress];
}

+ (NSString *)wifiSSID{
    @try {
        NSString *wifiName = nil;
        CFArrayRef myArray = CNCopySupportedInterfaces();
        if (myArray != nil) {
            CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
            if (myDict != nil) {
                NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict);
                wifiName = [dict valueForKey:@"SSID"];
            }
        }
        return wifiName;
    }@catch (NSException *exception) {
        return @"";
    }
}


+ (NSString *)getLocation{
    @try {
        //if (![Utility checkIsAppContestOn]) {
            CLLocationManager *locationManager = [[CLLocationManager alloc] init];
            if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
                [locationManager requestWhenInUseAuthorization];
            }
            CLLocationCoordinate2D currentCoordinate = locationManager.location.coordinate;
            NSString *latitudeStr = [NSString stringWithFormat:@"%.6f",currentCoordinate.latitude];
            NSString *longtitudeStr = [NSString stringWithFormat:@"%.6f",currentCoordinate.longitude];
            NSString *resulr = [NSString stringWithFormat:@"%@,%@",latitudeStr, longtitudeStr];
            return resulr;
        //}else{
        //    return @"0.001,0.001";
        //}
    }
    @catch (NSException *exception) {
        return @"";
    }
}

+ (NSDictionary *)logSP {
    NSMutableDictionary *logDic = NSMutableDictionary.dictionary;
    [logDic setObject:[ALDeviceInfoTools getMemory] forKey:@"m"];
    
    return (NSDictionary *)logDic;
}

+ (NSString *)getMemory {
    long long m = [NSProcessInfo processInfo].physicalMemory;
    NSString *mm = [NSNumber numberWithLong:m].stringValue;
    return mm;
}

+ (void) updateNotificationSettingsStatus {
    [ALUtils getUserNotificationSettingsWithCompletionHandler:^(ALNotificationType types) {
        BOOL isAllowed = (types != ALNotificationTypeNone);
        [[NSUserDefaults standardUserDefaults] setObject:isAllowed ? @"true":@"false" forKey:@"LFLocalKeyIsNotificationAllowed"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }];
}


@end
